/*
 * BSM6.0
 *
 * Copyright 2012-2013 (C) SINODATA CO., LTD. All Rights Reserved.
 */
package com.sinodata.bsm.center.message;

import java.io.Serializable;
import java.lang.reflect.Method;

import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;

import org.apache.log4j.Logger;

import com.sinodata.bsm.center.util.spring.SpringContextHolder;
import com.sinodata.bsm.common.message.BsmActiveMQFactory;
import com.sinodata.bsm.common.message.ServiceMessage;

/**
 * <p>
 * Description: 
 * </p>
 *
 * @author tangli
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-5-7 下午5:23:13          tangli_ITSM        1.0         To create
 * </p>
 *
 * @since 
 * @see     
 */
public class ProbeRequestListener implements MessageListener {
    private static final Logger logger = Logger.getLogger("message");
    private static ProbeRequestListener instance = new ProbeRequestListener();
    private Session session;
    private Destination destination;
    private final String queueName = "SYNC_PTC";
    private final int ackMode = Session.AUTO_ACKNOWLEDGE;

    private ProbeRequestListener() {
        try {
            session = BsmActiveMQFactory.getInstance().getSession(false, ackMode);

            destination = session.createQueue(queueName);
            MessageConsumer consumer = null;
            consumer = session.createConsumer(destination);
            clean(consumer);
            consumer.setMessageListener(this);
            logger.info("[TIP]>>>>>Start Listen Syn Queue.");
        } catch (Exception ex) {
            logger.error("[ERROR]>>>>>create message queue:" + this.queueName, ex);
        }
    }

    public static ProbeRequestListener getInstance() {
        return instance;
    }

    private void clean(MessageConsumer consumer) {
        while (true) {
            try {
                Message msg = consumer.receive(1000L);
                if (msg == null) {
                    //                    logger.info("队列中没有消息");
                    break;
                }
                //                else{
                //                    logger.info("删除消息："+msg);
                //                    try {
                //                        MessageProducer replyProducer;
                //                        replyProducer = session.createProducer(null);
                //                        replyProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
                //                        replyProducer.send(msg.getJMSReplyTo(), session.createObjectMessage("消息已过期"));
                //                    } catch (Exception e) {
                //                        logger.fatal("回复会话失败", e);
                //                    }
                //                    
                //                }
            } catch (JMSException e) {
                logger.error("[ERROR]>>>>>Failed To Clean Syn Queue", e);
                break;
            }
        }
    }

    /**
     * 注意，此队列是同步对列，注动接收消息，方法没有执行完之后，将不会异步执行后面发过来的请求消息
     */
    @Override
    public void onMessage(Message message) {
        if (message instanceof ServiceMessage) {
            ServiceMessage m = (ServiceMessage) message;
            logger.info(">>>>>>:SrvId[" + m.getSrvId() + "] method[" + m.getMethod() + "]");
        }
        Serializable response = null;
        try {
            response = dealwith(message);
        } catch (Exception e) {
            logger.error("消息处理失败:", e);
        }
        if (response == null) {
            response = "ERROR:处理失败";
        }
        MessageProducer replyProducer;
        try {
            replyProducer = session.createProducer(null);
            replyProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
            replyProducer.send(message.getJMSReplyTo(), session.createObjectMessage(response));
        } catch (Exception e) {
            logger.error("回复同步队列失败", e);
        }
    }

    public Serializable dealwith(Message message) {
        try {
            ObjectMessage objmsg = (ObjectMessage) message;
            Object msg = objmsg.getObject(); //待序列化的消息
            if (msg instanceof ServiceMessage) {
                ServiceMessage serviceMessage = (ServiceMessage) msg;
                String serviceId = serviceMessage.getSrvId();
                String methodName = serviceMessage.getMethod();
                Object[] params = serviceMessage.getParams();
                boolean isNeedReply = serviceMessage.isNeedReply();
                Object service = SpringContextHolder.getBean(serviceId);
                Class[] paramTypes = null;
                if (params != null) {
                    paramTypes = new Class[params.length];
                    for (int i = 0; i < paramTypes.length; i++) {
                        paramTypes[i] = params[i].getClass();
                    }
                }
                Method method;
                try {
                    method = service.getClass().getDeclaredMethod(methodName, paramTypes);
                } catch (Exception e) {
                    logger.error("failed to get method", e);
                    return null;
                }
                Serializable response = null;
                try {
                    response = (Serializable) method.invoke(service, params);
                } catch (Exception e) {
                    logger.error("Method invocation failure:" + serviceMessage.toString());
                    logger.error(e);
                    return null;
                }
                return response;
            }
            return null;
        } catch (Exception e) {
            logger.error("failed to get method", e);
            return null;
        }
    }
}
